﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace calculator
{
    class ExpressionParser
    {
        private string expression;
        private string[] validOperations = new string[] { "AND", "OR", "XOR", "NOT", "NAND", "NOR", "IFF", "IFN", "XNOR" };
        
        public ExpressionParser(string expression)
        {
            if (expression == "" || expression == null)
                throw new ArgumentException("You can't have an empty/null string.");
            
            this.expression = expression;
        }

        public void setChecker(string expression)
        {
            if (expression == "" || expression == null)
                throw new ArgumentException("You can't have an empty/null string.");

            this.expression = expression;
        }

        public bool basicCheck()//This does all non-complicated checks like are there illegal characters and different amount of  Parantheses
        {
            int numberOfOpeningParantheses = 0;
            int numberOfClosingParantheses = 0;
            foreach (char letter in expression.ToUpper())
            {
                if ((letter < 'A' || letter > 'Z') && (letter != '(' && letter != ')' & letter != ' '))
                    return false;
                if (letter == '(')
                    numberOfOpeningParantheses++;
                else if (letter == ')')
                    numberOfClosingParantheses++;
            }

            if (numberOfClosingParantheses != numberOfOpeningParantheses)
                return false;

            return true;
        }

        private bool checkInternalString(string subExpression)
        {
            int startOfOperation = 0;
            int endOfOperation = 0;

            foreach (string validOperation in validOperations)
            {
                while (true)
                {
                    if (subExpression.ToUpper().Contains(" " + validOperation + " "))
                    {
                        startOfOperation = subExpression.IndexOf(validOperation) - 2;
                        endOfOperation = 4+validOperation.Length;

                        if (startOfOperation < 0 || endOfOperation > subExpression.Length)
                            return false;
                        else
                        {
                            string stringToReplace = subExpression.Substring(startOfOperation, endOfOperation);
                            subExpression = subExpression.Replace(stringToReplace, "#");
                        }
                    }
                    else
                        break;
                }
            }

            if (subExpression == "#")
                return true;
            else if (subExpression.Length == 1 && Convert.ToChar(subExpression.ToUpper()) >= 'A' && Convert.ToChar(subExpression.ToUpper()) <= 'Z')
                return true;
            else
                return false;
        }

        public bool checkString()
        {
            int lastOpeningParantheses = -1;//This will hold onto the place of the last (
            int firstClosingParantheses = -1;//This will hold onto the place of the first )

            while (true)
            {
                lastOpeningParantheses = -1;
                firstClosingParantheses = -1;
                for (int index = 0; index < expression.Length; index++)
                {
                    if (expression[index] == '(')
                        lastOpeningParantheses = index;
                    else if (expression[index] == ')')
                    {
                        firstClosingParantheses = index;
                        break;
                    }
                }
                
                if (lastOpeningParantheses != -1 && firstClosingParantheses != -1)
                {
                    string theBracketString = expression.Substring(lastOpeningParantheses + 1, (firstClosingParantheses - lastOpeningParantheses - 1));

                    if (checkInternalString(theBracketString) == false)
                        return false;

                    expression = expression.Replace(expression.Substring(lastOpeningParantheses, (firstClosingParantheses - lastOpeningParantheses+1)), "#");
                }
                else
                    break;
            }

            if (checkInternalString(expression) == true || expression == "#")
                return true;
            else
                return false;
        }
    }
}
